//
//  ZZCCordovaBaseWebViewVC.swift
//  ewgShop
//
//  Created by zzc on 2019/8/5.
//  Copyright © 2019 zzc. All rights reserved.
//

import UIKit
import WebKit
import Foundation



class ZZCCordovaBaseWebViewVC: CDVViewController {

//    struct Person {
//        private(set) var name : String!
//
//        init(_ name: String) {
//            self.name = name
//        }
//    }
    let CDV_MESSAGE_HANDLER_NAME                    = "cordova"
    let OBSERVE_READY_STATE_MESSAGE_HANDLER_NAME    = "ObserveReadyState"
    let QUERY_READY_STATE_MESSAGE_HANDLER_NAME      = "QueryReadyState"
    let QUERY_REDIRECT_STATE_MESSAGE_HANDLER_NAME   = "QueryRedirectState"
    
    var readyState = ZZCWKWebViewReadyState.Loading;
    var redirectPage = false;
    var currentHref : String?
    var wkWebView : WKWebView{
        get{
//            NSAssert(self.webView.isKind(of: WKWebView.self),"Please Use WKWebView Instead");
            return self.webView as! WKWebView
        }
    }
//    懒加载
    lazy var requestParseManager : ZZCWKURLRequestParseManager = {
        let reqManager = ZZCWKURLRequestParseManager.init()
        return reqManager
    }()
    
    var wkNavigationDelegate : ZZCBaseCDVWKNavigationDelegate?
    var wkScriptMessageHandler : ZZCBaseScriptMeaasgeHandler?
    
    
    override func viewDidLoad() {
        self.readyState = ZZCWKWebViewReadyState.Loading
        self.redirectPage = false
        
        super.viewDidLoad()
        
        self.view.backgroundColor = UIColor.white
    
        // Do any additional setup after loading the view.
        
        self.setupWKWebViewEngine()
    }
    
    //MARK: URL相关处理
    func setUpRequestParseManager(){
        
    }
    //MARK: 设置webViewEngine
    func setupWKWebViewEngine(){
        
        self.wkNavigationDelegate = ZZCBaseCDVWKNavigationDelegate()
        self.wkNavigationDelegate?.viewController = self;
        self.wkScriptMessageHandler = ZZCBaseScriptMeaasgeHandler()
        self.wkScriptMessageHandler?.viewController = self;
        
        self.webViewEngine.update(withInfo: [kCDVWebViewEngineWKNavigationDelegate :self.wkNavigationDelegate!, kCDVWebViewEngineScriptMessageHandlers: [
            QUERY_READY_STATE_MESSAGE_HANDLER_NAME: self.wkScriptMessageHandler,
            OBSERVE_READY_STATE_MESSAGE_HANDLER_NAME: self.wkScriptMessageHandler,
            QUERY_REDIRECT_STATE_MESSAGE_HANDLER_NAME: self.wkScriptMessageHandler
        ]
    ]);
    
        self.userContentController().addUserScript(self.userScriptOfCordova());
        
        self.userContentController().addUserScript(self.userScriptOfLoadReadyState());
        
        self.userContentController().addUserScript(self.userScriptOfFinishReadyState());
        self.userContentController().addUserScript(self.userScriptOfLoadRedirectState());
    }
    
//MARK: 脚本注入
    func userScriptOfCordova() -> WKUserScript {
        
        let js = self.jsSourceOfFileName(fileName: "web_cordova")
        
        let userScript = WKUserScript.init(source: js, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false);
        return userScript
    }
    
    func userScriptOfLoadReadyState() -> WKUserScript {
        let js = String.init(format: "window.webkit.messageHandlers.%@.postMessage(document.readyState);", QUERY_READY_STATE_MESSAGE_HANDLER_NAME)
        let userScript = WKUserScript.init(source: js, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false);
        return userScript
    }
    
    func userScriptOfFinishReadyState() -> WKUserScript {
        let js = String.init(format: "document.onreadystatechange = statechange;function statechange(){window.webkit.messageHandlers.%@.postMessage(document.readyState);", OBSERVE_READY_STATE_MESSAGE_HANDLER_NAME)
        let userScript = WKUserScript.init(source: js, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false);
        return userScript
    }
    
    func userScriptOfLoadRedirectState() -> WKUserScript {
        let js = String.init(format: "(function(){isRedirect=0;metas=window.document.head.getElementsByTagName('meta');for(var i=0;i<metas.length;i++){if(metas[i].getAttribute('http-equiv') == 'refresh'){isRedirect=1;break;}};window.webkit.messageHandlers.%@.postMessage(isRedirect);})();", QUERY_REDIRECT_STATE_MESSAGE_HANDLER_NAME)
        let userScript = WKUserScript.init(source: js, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false);
        return userScript
    }
    
    func userContentController() -> WKUserContentController {
        return self.wkWebViewConfiguration().userContentController
    }
    
    func wkWebViewConfiguration() -> WKWebViewConfiguration {
        return self.wkWebViewEngine().configuration;
    }
    
    
    func wkWebViewEngine() -> WKWebView {
        return self.webViewEngine!.engineWebView as! WKWebView;
    }
    
    func jsOfLocationHref() -> String {
        return "location.href";
    }
    
    func jsSourceOfFileName(fileName:String) -> String {
        var source = NSMutableString.init();
        let sourcePath = Bundle.main.path(forResource: fileName, ofType: "js")
        if (sourcePath != nil) {
            do{
                source = try NSMutableString.init(contentsOfFile: sourcePath!, encoding: String.Encoding.utf8.rawValue)
            }catch{}
        }
        return source as String;
    }
    
    
    //MARK: --WKNavigationDelegate
    @objc func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) -> Int {
        if self.readyState.rawValue > 0{
            let navigationActionPolicy = self.requestParseManager.navigationPolicyForURL(url: navigationAction.request.url as NSURL?)
            return navigationActionPolicy
        }
        return -1
    }
    
    func webView(_ webView: WKWebView, decideResponsePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) -> Int{
        return -1;
    }
    
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        
    }
    
    func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
        
    }
    
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        
    }
    
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        self.requestParseManager.handleRequestURL(requestURL: webView.url as NSURL?)
    }
    
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        self.readyState = ZZCWKWebViewReadyState.Complete
    }
    
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        
    }
    
    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
//        self.relo
    }
    
    
    //MARK: Private
    func reloadRequestIfNeeded(){
        if self.wkWebView.url != nil {
            return
        }
        
        if self.isBlankView(webview: self.wkWebView) == false {
            return;
        }
        let request = URLRequest.init(url: URL.init(string: self.startPage)!, cachePolicy: URLRequest.CachePolicy.useProtocolCachePolicy, timeoutInterval: 20.0)
        self.webViewEngine.load(request)
    }
    
    
    func isBlankView(webview:UIView) -> Bool {
        
        let wkCompositingViewClass : AnyClass = NSClassFromString("WKCompositingView")!
        if webView.isKind(of: wkCompositingViewClass.self){
            return false
        }
        for (_ ,obj) in webview.subviews.enumerated(){
            if self.isBlankView(webview: obj) == false{
                return false;
            }
        }
        return true;
    }
    
    //MARK: deinit handle
    deinit {
        self.wkWebView.configuration.userContentController.removeScriptMessageHandler(forName: QUERY_READY_STATE_MESSAGE_HANDLER_NAME)
        
        self.wkWebView.configuration.userContentController.removeScriptMessageHandler(forName: OBSERVE_READY_STATE_MESSAGE_HANDLER_NAME)
        
        self.wkWebView.configuration.userContentController.removeScriptMessageHandler(forName: QUERY_REDIRECT_STATE_MESSAGE_HANDLER_NAME)
    }
    
    
}
